package com.xnyzc.lhy.resource.util.invoice;

import com.baiwang.bop.client.BopException;
import com.baiwang.bop.client.IBopClient;
import com.baiwang.bop.client.ILoginClient;
import com.baiwang.bop.client.impl.BopRestClient;
import com.baiwang.bop.client.impl.PostLogin;
import com.baiwang.bop.request.impl.LoginRequest;
import com.baiwang.bop.request.impl.invoice.common.InvoiceDetails;
import com.baiwang.bop.request.impl.invoice.impl.*;
import com.baiwang.bop.respose.entity.*;
import com.xnyzc.lhy.common.exception.InvoiceException;
import com.xnyzc.lhy.common.penum.invoice.EInvoiceErrorCode;
import com.xnyzc.lhy.resource.entity.invoice.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

/**
 * <p>
 * 百望云电子发票工具类
 * </p>
 *
 * @author haoyfa
 * @since 2019-10-24
 */
@Service
@Slf4j
public class BopInvoiceUtils {
    @Value("${global.invoice.bop.url}")
    private String url;

    @Value("${global.invoice.bop.appKey}")
    private String appKey;

    @Value("${global.invoice.bop.appSecret}")
    private String appSecret;

    @Value("${global.invoice.bop.username}")
    private String username;

    @Value("${global.invoice.bop.password}")
    private String password;

    @Value("${global.invoice.bop.UUID}")
    private String UUID;

    private String token = "";

    public void initializtion(){
        LoginResponse loginResponse = this.loginRequest();
        // 获取token
        token =loginResponse.getAccess_token();
    }

    private void tokenValidation(){
        if("".equals(this.token)){
            log.error("百望云发票调用工具类没有初始化token");
            throw InvoiceException.create(EInvoiceErrorCode.initializtionError);
        }
    }

    /**
     * 获取token
     * @return
     */
    public String getToken() {
        LoginResponse loginResponse = this.loginRequest();
        // 获取token
        token = loginResponse.getAccess_token();
        return token;
    }

    /**
     * 登录请求
     * @return 登录相应类
     */
    public LoginResponse loginRequest() {
        ILoginClient loginClient = new PostLogin(url);
        LoginRequest loginRequest = new LoginRequest();
        loginRequest.setAppkey(appKey);
        loginRequest.setAppSecret(appSecret);
        loginRequest.setUserName(username);
        loginRequest.setPasswordMd5(password);
        loginRequest.setUserSalt(UUID);

        try {
            return loginClient.login(loginRequest);
        }
        catch (BopException bopException){
            log.error("百望云发票调用工具类登录错误");
            throw InvoiceException.create(EInvoiceErrorCode.loginError);
        }

    }

    /**
     * 监控信息查询
     */
    public MonitorResponse monitorRequest(MonitorRequest request){
        this.tokenValidation();

        IBopClient client = new BopRestClient(url, appKey, appSecret);
        try{
            return client.execute(request, token, MonitorResponse.class);
        }
        catch (BopException bopException) {
            log.error("百望云发票调用工具类调用监控信息查询错误");
            throw InvoiceException.create(EInvoiceErrorCode.executeError, bopException.getSubMessage());
        }
    }

    /**
     * 发票开具
     */
    public InvoiceOpenResponse invoiceOpenRequest(InvoiceOpenRequest request) {
        this.tokenValidation();

        IBopClient client = new BopRestClient(url, appKey, appSecret);
        try {
            return client.execute(request, token, InvoiceOpenResponse.class);
        } catch (BopException bopException) {
            log.error("百望云发票调用工具类调用监发票开具错误");
            throw InvoiceException.create(EInvoiceErrorCode.executeError, bopException.getSubMessage());
        }
    }

    /**
     * 发票查询
     */
    public InvoiceQueryResponse invoiceQueryRequest(InvoiceQueryRequest request) {
        this.tokenValidation();

        IBopClient client = new BopRestClient(url, appKey, appSecret);
        try {
            return client.execute(request, token, InvoiceQueryResponse.class);
        } catch (BopException bopException) {
            log.error("百望云发票调用工具类调用发票查询错误");
            throw InvoiceException.create(EInvoiceErrorCode.executeError, bopException.getSubMessage());
        }
    }

    /**
     * 发票作废
     */
    public InvoiceInvalidResponse invoiceInvalidRequest(InvoiceInvalidRequest request) {
        this.tokenValidation();

        IBopClient client = new BopRestClient(url, appKey, appSecret);
        try {
            return client.execute(request, token, InvoiceInvalidResponse.class);
        } catch (BopException bopException) {
            log.error("百望云发票调用工具类调用发票作废错误");
            throw InvoiceException.create(EInvoiceErrorCode.executeError, bopException.getSubMessage());
        }
    }

    /**
     * 板式文件生成
     */
    public FormatfileBuildResponse formatfileBuildRequest(FormatfileBuildRequest request) {
        this.tokenValidation();

        IBopClient client = new BopRestClient(url, appKey, appSecret);
        try {
            return client.execute(request, token, FormatfileBuildResponse.class);
        } catch (BopException bopException) {
            log.error("百望云发票调用工具类调用板式文件生成错误");
            throw InvoiceException.create(EInvoiceErrorCode.executeError, bopException.getSubMessage());
        }
    }

    /**
     * 板式文件查询
     */
    public FormatfileQueryResponse formatfileQueryRequest(FormatfileQueryRequest request) {
        this.tokenValidation();

        IBopClient client = new BopRestClient(url, appKey, appSecret);
        try {
            return client.execute(request, token, FormatfileQueryResponse.class);
        } catch (BopException bopException) {
            log.error("百望云发票调用工具类调用板式文件查询错误");
            throw InvoiceException.create(EInvoiceErrorCode.executeError, bopException.getSubMessage());
        }
    }

    /**
     * 转换百望云开发票服务请求参数
     * @param invoiceParam
     * @return
     */
    public InvoiceOpenRequest convertInvoiceOpenRequest(InvoiceParam invoiceParam) {
        InvoiceOpenRequest invoiceOpenRequest = new InvoiceOpenRequest();
        //开发票申请部分信息
        InvoiceApplyParam  invoiceApplyParam  = invoiceParam.getInvoiceApplyParam();
        //开发票发票部分信息
        InvoiceInfoParam invoiceInfoParam = invoiceParam.getInvoiceInfoParam();
        //开发票发票详情信息
        List<InvoiceDetailParam> invoiceDetailListParam = invoiceParam.getInvoiceDetailListParam();

        /**
         * 申请信息部分
         */

        //开票流水号
        invoiceOpenRequest.setSerialNo(invoiceApplyParam.getSerialNo());
        //设备类型
        invoiceOpenRequest.setDeviceType(invoiceApplyParam.getDeviceType());
        //业务请求流水号
        invoiceOpenRequest.setReqSerialNumber(invoiceApplyParam.getReqSerialNumber());
        //第三方业务系统ID
        invoiceOpenRequest.setBusinessId(invoiceApplyParam.getBusinessId());
        //征税方式
        invoiceOpenRequest.setTaxationMode(invoiceApplyParam.getTaxationMode());
        //税控盘编号
        invoiceOpenRequest.setTaxDiskNo(invoiceApplyParam.getTaxDiskNo());
        //发票票样
        invoiceOpenRequest.setInvoiceSample(invoiceApplyParam.getInvoiceSample());
        //开具超过限额自动拆分
        invoiceOpenRequest.setAutoSplit(invoiceApplyParam.getAutoSplit());

        /**
         * 发票信息部分
         */

        //发票种类编码
        invoiceOpenRequest.setInvoiceTypeCode(invoiceInfoParam.getInvoiceTypeCode());
        //特殊票种标记
        invoiceOpenRequest.setInvoiceSpecialMark(invoiceInfoParam.getInvoiceSpecialMark());
        //销方单位税号
        invoiceOpenRequest.setSellerTaxNo(invoiceInfoParam.getSellerTaxNo());
        //开票点编码
        invoiceOpenRequest.setInvoiceTerminalCode(invoiceInfoParam.getInvoiceTerminalCode());
        //销方名称
        invoiceOpenRequest.setSellerName(invoiceInfoParam.getSellerName());
        //销方地址电话
        invoiceOpenRequest.setSellerAddressPhone(invoiceInfoParam.getSellerAddressPhone());
        //销方银行账号
        invoiceOpenRequest.setSellerBankAccount(invoiceInfoParam.getSellerBankAccount());
        //组织机构代码
        invoiceOpenRequest.setOrganizationCode(invoiceInfoParam.getOrganizationCode());
        //购方单位税号
        invoiceOpenRequest.setBuyerTaxNo(invoiceInfoParam.getBuyerTaxNo());
        //购方单位名称
        invoiceOpenRequest.setBuyerName(invoiceInfoParam.getBuyerName());
        //购方地址及电话
        invoiceOpenRequest.setBuyerAddressPhone(invoiceInfoParam.getBuyerAddressPhone());
        //购方开户行及账号
        invoiceOpenRequest.setBuyerBankAccount(invoiceInfoParam.getBuyerBankAccount());
        //开票人
        invoiceOpenRequest.setDrawer(invoiceInfoParam.getDrawer());
        //复核人
        invoiceOpenRequest.setChecker(invoiceInfoParam.getChecker());
        //收款人
        invoiceOpenRequest.setPayee(invoiceInfoParam.getPayee());
        //开票类型
        invoiceOpenRequest.setInvoiceType(invoiceInfoParam.getInvoiceType());
        //红字信息表编号
        invoiceOpenRequest.setRedInfoNo(invoiceInfoParam.getRedinfoNo());
        //原发票代码
        invoiceOpenRequest.setOriginalInvoiceCode(invoiceInfoParam.getInvoiceTerminalCode());
        //原发票号码
        invoiceOpenRequest.setOriginalInvoiceNo(invoiceInfoParam.getNotificationNo());
        //清单标志
        invoiceOpenRequest.setInvoiceListMark(invoiceInfoParam.getInvoicelistMark());
        //扣除额
        if(invoiceInfoParam.getDeductibleAmount() != null) {
            invoiceOpenRequest.setDeductibleAmount(invoiceInfoParam.getDeductibleAmount().toString());
        }
        //合计金额
        if(invoiceInfoParam.getInvoiceTotalPrice() != null) {
            invoiceOpenRequest.setInvoiceTotalPrice(invoiceInfoParam.getInvoiceTotalPrice().toString());
        }
        //合计税额
        if(invoiceInfoParam.getInvoiceTotalTax() != null) {
            invoiceOpenRequest.setInvoiceTotalTax(invoiceInfoParam.getInvoiceTotalTax().toString());
        }
        //价税合计
        if(invoiceInfoParam.getInvoiceTotalPricetax() != null) {
            invoiceOpenRequest.setInvoiceTotalPriceTax(invoiceInfoParam.getInvoiceTotalPricetax().toString());
        }
        //通知单编号
        invoiceOpenRequest.setNotificationNo(invoiceInfoParam.getNotificationNo());
        //签名值参数
        invoiceOpenRequest.setSignatureParameter(invoiceInfoParam.getSignatureParameter());
        //签名值参数
        invoiceOpenRequest.setSignatureParameter(invoiceInfoParam.getSignatureParameter());
        //商品编码版本号
        invoiceOpenRequest.setGoodsCodeVersion(invoiceInfoParam.getGoodsCodeVersion());
        //综合税率
        if(invoiceInfoParam.getConsolidatedTaxRate() != null) {
            invoiceOpenRequest.setConsolidatedTaxRate(invoiceInfoParam.getConsolidatedTaxRate().toString());
        }
        //备注
        invoiceOpenRequest.setRemarks(invoiceInfoParam.getRemarks());

        /**
         * 发票明细部分
         */
        List<InvoiceDetails> invoiceDetailsList = new ArrayList<InvoiceDetails>(invoiceDetailListParam.size());
        for (InvoiceDetailParam invoiceDetailParam: invoiceDetailListParam) {
            InvoiceDetails invoiceDetail = new InvoiceDetails();

            //明细行号
            invoiceDetail.setGoodsLineNo(invoiceDetailParam.getGoodsLineNo());
            //发票行性质
            invoiceDetail.setGoodsLineNature(invoiceDetailParam.getGoodsLineNature());
            //商品编码
            invoiceDetail.setGoodsCode(invoiceDetailParam.getGoodsCode());
            //自行编码
            invoiceDetail.setGoodsExtendCode(invoiceDetailParam.getGoodsExtendCode());
            //商品名称
            invoiceDetail.setGoodsName(invoiceDetailParam.getGoodsName());
            //商品税目
            invoiceDetail.setGoodsTaxItem(invoiceDetailParam.getGoodsTaxItem());
            //规格型号
            invoiceDetail.setGoodsSpecification(invoiceDetailParam.getGoodsSpecification());
            //计量单位
            invoiceDetail.setGoodsUnit(invoiceDetailParam.getGoodsUnit());
            //商品数量
            invoiceDetail.setGoodsQuantity(invoiceDetailParam.getGoodsQuantity());
            //商品单价
            if(invoiceDetailParam.getGoodsPrice() != null) {
                invoiceDetail.setGoodsPrice(invoiceDetailParam.getGoodsPrice().toString());
            }
            //金额
            if(invoiceDetailParam.getGoodsTotalPrice() != null) {
                invoiceDetail.setGoodsTotalPrice(invoiceDetailParam.getGoodsTotalPrice().toString());
            }
            //税额
            if(invoiceDetailParam.getGoodsTotalTax() != null) {
                invoiceDetail.setGoodsTotalTax(invoiceDetailParam.getGoodsTotalTax().toString());
            }
            //税率
            if(invoiceDetailParam.getGoodsTaxRate() != null) {
                invoiceDetail.setGoodsTaxRate(invoiceDetailParam.getGoodsTaxRate().toString());
            }
            //折行对应行号
            invoiceDetail.setGoodsDiscountLineNo(invoiceDetailParam.getGoodsDiscountLineNo());
            //含税标志
            invoiceDetail.setPriceTaxMark(invoiceDetailParam.getPriceTaxMark());
            //增优惠政策类型
            invoiceDetail.setVatSpecialManagement(invoiceDetailParam.getVatSpecialManagement());
            //零税率标识
            invoiceDetail.setFreeTaxMark(invoiceDetailParam.getFreeTaxMark());
            //是否使用优惠政策
            invoiceDetail.setPreferentialMark(invoiceDetailParam.getPreferentialMark());

            invoiceDetailsList.add(invoiceDetail);
        }

        invoiceOpenRequest.setInvoiceDetailsList(invoiceDetailsList);

        return invoiceOpenRequest;
    }

    /**
     * 板式文件生成参数转换
     * @param invoiceFormatFileParam
     * @return
     */
    public FormatfileBuildRequest convertFormatfileBuildRequest(InvoiceFormatFileParam invoiceFormatFileParam){
        FormatfileBuildRequest formatfileBuildRequest = new FormatfileBuildRequest();

        /**
         * 纳税人识别号
         */
        formatfileBuildRequest.setSellerTaxNo(invoiceFormatFileParam.getSellerTaxNo());

        /**
         * 开票流水号,流水号和发票号码代码二选一必填
         */
        formatfileBuildRequest.setSerialNo(invoiceFormatFileParam.getSerialNo());

        /**
         * 发票代码,流水号和发票号码代码二选一必填
         */
        formatfileBuildRequest.setInvoiceCode(invoiceFormatFileParam.getInvoiceCode());

        /**
         * 发票号码
         */
        formatfileBuildRequest.setInvoiceNo(invoiceFormatFileParam.getInvoiceNo());

        /**
         * 推送标志 0：不推送 1：推送（邮箱电话必填一个）
         */
        formatfileBuildRequest.setPushType(invoiceFormatFileParam.getPushType());

        /**
         * 推送至第三方渠道
         */
        formatfileBuildRequest.setPushChannel(invoiceFormatFileParam.getPushChannel());

        /**
         * 购方客户邮箱
         */
        formatfileBuildRequest.setBuyerEmail(invoiceFormatFileParam.getBuyerEmail());

        /**
         * 购方客户电话
         */
        formatfileBuildRequest.setBuyerPhone(invoiceFormatFileParam.getBuyerPhone());

        return formatfileBuildRequest;
    }

    /**
     * 发票作废参数转化
     * @param invoiceInvalidParam
     * @return
     */
    public InvoiceInvalidRequest convertInvoiceInvalidParam(InvoiceInvalidParam invoiceInvalidParam) {
        InvoiceInvalidRequest invoiceInvalidRequest = new InvoiceInvalidRequest();

        /**
         * 设备类型 0税控服务器，1税控盘
         */
        invoiceInvalidRequest.setDeviceType(invoiceInvalidParam.getDeviceType());

        /**
         * 作废类型 0：空白票作废 1：已开票作废
         */
        invoiceInvalidRequest.setInvoiceInvalidType(invoiceInvalidParam.getInvoiceInvalidType());

        /**
         * 纳税人识别号
         */
        invoiceInvalidRequest.setSellerTaxNo(invoiceInvalidParam.getSellerTaxNo());

        /**
         * 发票种类编码:004:增值税专用发票，005:机动车销售统一发票，007:增值税普通发票，025：增值税卷式发票
         */
        invoiceInvalidRequest.setInvoiceTypeCode(invoiceInvalidParam.getInvoiceTypeCode());

        /**
         * 开票点编码
         */
        invoiceInvalidRequest.setInvoiceTerminalCode(invoiceInvalidParam.getInvoiceTerminalCode());

        /**
         * 发票代码
         */
        invoiceInvalidRequest.setInvoiceCode(invoiceInvalidParam.getInvoiceCode());

        /**
         * 发票号码
         */
        invoiceInvalidRequest.setInvoiceNo(invoiceInvalidParam.getInvoiceNo());

        /**
         * 税控盘编号，设备类型为1时必填
         */
        invoiceInvalidRequest.setTaxDiskNo(invoiceInvalidParam.getTaxDiskNo());

        /**
         * 作废人
         */
        invoiceInvalidRequest.setInvoiceInvalidOperator(invoiceInvalidParam.getInvoiceInvalidOperator());

        return invoiceInvalidRequest;
    }
}
